package com.demo.base.redis;

import com.demo.base.json.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.stereotype.Component;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by ethan on 2017/3/10.
 */
@Component
public class RedisTemplateFactory {

    private ObjectMapper objectMapper = JSON.createObjectMapper();

    private RedisConnectionFactory connectionFactory;

    private Map<Type, ObjectRedisTemplate<?>> redisTemplateMap = new HashMap<>();

    public RedisTemplateFactory(RedisConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }

    public <T> ObjectRedisTemplate<T> create(TypeReference<T> typeReference) {
        return create(TypeFactory.defaultInstance().constructType(typeReference).getRawClass());
    }

    public <T> ObjectRedisTemplate<T> create(Class dataClass) {
        if (!redisTemplateMap.containsKey(dataClass)) {
            synchronized (dataClass.getTypeName()) {
                if (!redisTemplateMap.containsKey(dataClass)) {
                    redisTemplateMap.put(dataClass, createRedisTemplate(dataClass));
                }
            }
        }
        return (ObjectRedisTemplate<T>) redisTemplateMap.get(dataClass);
    }

    private <T> ObjectRedisTemplate<T> createRedisTemplate(Class type) {
        Jackson2JsonRedisSerializer<T> serializer = new Jackson2JsonRedisSerializer<T>(type);
        serializer.setObjectMapper(this.objectMapper);
        return new ObjectRedisTemplate<>(connectionFactory, serializer);
    }
}
